package com.yang.core.extension;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.support.SpringFactoriesLoader;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 扩展注册中心
 * 负责管理所有的扩展点
 */
@Slf4j
public class ExtensionRegistry {

    private static final Map<String, RestClientExtension> EXTENSIONS = new ConcurrentHashMap<>();
    private static final Map<ExtensionPoint.Category, List<RestClientExtension>> CACHED_EXTENSIONS = new ConcurrentHashMap<>();

    /**
     * 注册扩展
     */
    public static void register(RestClientExtension extension) {
        if (extension == null || !extension.isEnabled()) {
            return;
        }

        String name = extension.getName();
        EXTENSIONS.put(name, extension);
        CACHED_EXTENSIONS.clear(); // 清除缓存

        log.info("注册扩展: {}", name);
    }

    /**
     * 注销扩展
     */
    public static void unregister(String name) {
        RestClientExtension removed = EXTENSIONS.remove(name);
        if (removed != null) {
            CACHED_EXTENSIONS.clear();
            removed.destroy();
            log.info("注销扩展: {}", name);
        }
    }

    /**
     * 获取所有扩展
     */
    public static List<RestClientExtension> getAllExtensions() {
        return new ArrayList<>(EXTENSIONS.values())
                .stream()
                .sorted(Comparator.comparingInt(RestClientExtension::getOrder))
                .collect(Collectors.toList());
    }

    /**
     * 根据分类获取扩展
     */
    public static List<RestClientExtension> getExtensions(ExtensionPoint.Category category) {
        return CACHED_EXTENSIONS.computeIfAbsent(category, cat ->
            EXTENSIONS.values().stream()
                .filter(ext -> {
                    ExtensionPoint annotation = ext.getClass().getAnnotation(ExtensionPoint.class);
                    return annotation != null && annotation.category() == cat;
                })
                .sorted(Comparator.comparingInt(RestClientExtension::getOrder))
                .collect(Collectors.toList())
        );
    }

    /**
     * 根据名称获取扩展
     */
    public static RestClientExtension getExtension(String name) {
        return EXTENSIONS.get(name);
    }

    /**
     * 自动发现并注册扩展
     */
    public static void autoDiscoverExtensions() {
        try {
            // 通过Spring Factories机制加载扩展
            List<RestClientExtension> extensions = SpringFactoriesLoader.loadFactories(
                RestClientExtension.class,
                ExtensionRegistry.class.getClassLoader()
            );

            for (RestClientExtension extension : extensions) {
                register(extension);
            }

            // 扫描classpath中带有ExtensionPoint注解的类
            scanAndRegisterExtensions();

        } catch (Exception e) {
            log.error("自动发现扩展失败", e);
        }
    }

    /**
     * 扫描并注册扩展
     */
    private static void scanAndRegisterExtensions() {
        // 这里可以使用反射工具类扫描classpath
        // 简化实现，实际项目中可以使用ClassPathScanningCandidateComponentProvider
        log.info("扫描并注册扩展点");
    }

    /**
     * 初始化所有扩展
     */
    public static void initializeAll() {
        EXTENSIONS.values().forEach(extension -> {
            try {
                extension.initialize();
            } catch (Exception e) {
                log.error("初始化扩展失败: {}", extension.getName(), e);
            }
        });
    }

    /**
     * 销毁所有扩展
     */
    public static void destroyAll() {
        EXTENSIONS.values().forEach(extension -> {
            try {
                extension.destroy();
            } catch (Exception e) {
                log.error("销毁扩展失败: {}", extension.getName(), e);
            }
        });
        EXTENSIONS.clear();
        CACHED_EXTENSIONS.clear();
    }

    /**
     * 获取扩展统计信息
     */
    public static Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalExtensions", EXTENSIONS.size());

        Map<ExtensionPoint.Category, Long> categoryStats = EXTENSIONS.values().stream()
            .collect(Collectors.groupingBy(
                ext -> {
                    ExtensionPoint annotation = ext.getClass().getAnnotation(ExtensionPoint.class);
                    return annotation != null ? annotation.category() : ExtensionPoint.Category.GENERAL;
                },
                Collectors.counting()
            ));

        stats.put("categoryStats", categoryStats);
        return stats;
    }
}